<?php
/**
 * cache.class
 * 
 * Caching mechanizm
 * 
 * @version:	0.2b
 * @package:	core
 * @author:	alex_ez
 * @created:	21 dec 2008
 *
 * @copyright:	(c) 2009 alex <qfox@ya.ru> yaroshevich aka alex_ez. All rights reserved.
 */

class cacher_file implements cacher_interface
{
	private $dir;
	protected $info;
	
	public function __construct() {
		$this->info = array( 'hits' => 0, 'misses' => 0 );
		$this->dir = CACHEPATH;
	}

	// This is the function you store information with
	function store($k,&$v,$ttl=null) {
 		list($dir, $filename) = $this->filename($k);

		if(!is_dir($dir))
			if(!mkdir($dir,0700,1))
				return false;

		if(!file_put_contents($filename,serialize($v)))
			return false;

		if($ttl>0)
			if(!touch($filename,time()+$ttl))
				return false;

		if (!file_exists($filename)||filemtime($filename)<time()-1)
			return false;

		return true;
	}

	function retrieve($k) {
		$this->info['misses']++;
 		list($dir, $filename) = $this->filename($k);

		if (!file_exists($filename))
			return false;

		if (filemtime($filename)<time())
			return false;

		$this->info['hits']++;
		$this->info['misses']--;
		return unserialize(file_get_contents($filename));
   }
   
   public function drop($k) {
 		list($dir, $filename) = $this->filename($k);
		
		if(!file_exists($filename))
			return false;
		
		return @unlink($filename);
	}

	protected function filename($k) {
		$info = pathinfo($this->dir . str_replace('::','-',$k) . '.cache');
		return array( $info['dirname'], $info['dirname'] .'/'. $info['basename'] );
	}

	/*public function retrieve($k) {
		if (false !== ($cachefile = fopen($this->_dir . $path, 'w')))
		{
			flock($cachefile, LOCK_EX);
			fwrite($cachefile, $data, strlen($data));
			flock($cachefile, LOCK_UN);
			fclose($cachefile);

			chmod($this->_dir . $path, 0664);
		}
		return apc_fetch($k);
	}

	public function store($k,&$v,$ttl=12) {
		return apc_store($k,$v,$ttl);
	}

	public function drop($k) {
		//@unlink();
		return apc_delete($k);
	}*/

	public function cleanup()
	{
		return false;
		//return apc_clear_cache('user');
	}
	
	public function info() {
		$info = $this->info;

		$renames = array('hits'=>'cache_hits','misses'=>'cache_misses');
		$result = array();
		foreach ($renames as $k => $l)
			$result[$l] = $info[$k];

		return $result;
	}

	/*public function store( $class, $method, $params )
	{
		if( !array_key_exists( $cache_name, $this->storage ) )
		{
			$filename = $this->get_cache_path( $class, $method, $params );
			$this->storage[ $cache_name ] = unserialize( file_get_contents( $this->_dir . $filename ) );
		}
		return $this->storage[ $cache_name ];
	}*/
	
	public function set( $class, $method, $params, &$value )
	{
		if (false !== ($cachefile = fopen($this->_dir . $path, 'w')))
		{
			flock($cachefile, LOCK_EX);
			fwrite($cachefile, $data, strlen($data));
			flock($cachefile, LOCK_UN);
			fclose($cachefile);
			
			chmod($this->_dir . $path, 0664);
		}
	}

	public function flush($class, $method, $params)
	{
		unset($this->storage[$this->cache_name($class, $method, $params)]);
		
		$path = $this->get_cache_path($class, $method, $params);
		
		if (file_exists($this->_dir.$path)) unlink($this->_dir.$path);
	}

	public function flush_all( $class, $methods )
	{
		if( is_array( $methods ) ) { foreach( $methods as $m ) $this ->flush_all( $class, $m ); return; }
		$method = $methods;
		
		$path = $this->_dir.$this->get_cache_dir( $class, $method );
		if( !is_dir( $path ) ) return;
		
		$dir = dir($path);
		while (false !== ($entry = $dir->read()))
		{
			if ($entry != '.' && $entry != '..')
			{
				unlink($path.$entry);
				unset($this->storage[$entry]);
			}
		}
	}
	
	public function flush_for_class($class)
	{
		$path = DIR_CACHE . $class . '/';
		
		if (is_dir($path))
		{
			exec('rm -rf ' . $path);
		}
		
		$this ->storage = array( );
	}

	public function is($class, $method, $params, $lifetime='0D')
	{
		if( $this ->is_off( ) ) return false;
		
		$this ->cmp = array( 'class' => $class, 'method' => $method, 'params' => $params );
		
		$cache_name = $this->cache_name( $class, $method, $params );
		if( array_key_exists( $cache_name, $this->storage ) ) return true;
		
		$lifetime = $this ->get_time_in_seconds( $lifetime );
		
		if( $lifetime && array_key_exists($cache_name, $this->storage) ) {
			return true;
		}
		
		$path = $this->get_cache_path( $class, $method, $params );
		
		$files_path = $this->_dir . $path;
		
		return ( file_exists($files_path)
			&& (filemtime($files_path)+$lifetime >= time()) );
	}
	
	private function check_path( &$class, &$method )
	{
		$cpath = $this->_dir . $this ->get_cache_dir( $class );
		$path = $this->_dir . $this ->get_cache_dir( $class, $method );
		
		if( !is_dir($path) )
		{
			mkdir( $path, 0770, true );
			chmod( $cpath, 0770 );
			chmod( $path, 0770 );
		}
	}
}


?>